package com.hrms.web.sys_user.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.hrms.jwt.JwtUtils;
import com.hrms.utils.ResultUtils;
import com.hrms.utils.ResultVo;
import com.hrms.web.sys_menu.entity.AssignTreeParm;
import com.hrms.web.sys_menu.entity.AssignTreeVo;
import com.hrms.web.sys_menu.entity.SysMenu;
import com.hrms.web.sys_menu.service.SysMenuService;
import com.hrms.web.sys_user.entity.*;
import com.hrms.web.sys_user.service.SysUserService;
import com.hrms.web.sys_user_role.entity.SysUserRole;
import com.hrms.web.sys_user_role.service.SysUserRoleService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Title: SysUserController
 * @Author zhanji
 * @Package com.hrms.web.sys_user.controller
 * @description:
 */
@RestController
@RequestMapping("/api/user")
public class SysUserController {

    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private DefaultKaptcha defaultKaptcha;

    @Resource
    private JwtUtils jwtUtils;
    @Resource
    private SysMenuService sysMenuService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private PasswordEncoder passwordEncoder;

    //新增
    @PreAuthorize("hasAuthority('sys:user:add')")
    @PostMapping
    public ResultVo addUser(@RequestBody SysUser sysUser) {
        sysUser.setCreateTime(LocalDateTime.now());
        //密码加密
        sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
        sysUserService.saveUser(sysUser);
        return ResultUtils.success("新增成功");
    }

    //编辑
    @PreAuthorize("hasAuthority('sys:user:edit')")
    @PutMapping
    public ResultVo editUser(@RequestBody SysUser sysUser) {
        sysUser.setUpdateTime(LocalDateTime.now());
        sysUserService.editUser(sysUser);
        return ResultUtils.success("编辑成功");
    }

    //删除
    @PreAuthorize("hasAuthority('sys:user:delete')")
    @DeleteMapping("/{userId}")
    public ResultVo deleteUser(@PathVariable("userId") Long userId) {
        sysUserService.deleteUser(userId);
        return ResultUtils.success("删除成功");
    }

    //分页
    @GetMapping("/getList")
    public ResultVo getList(UserParm parm){
        //构造分页对象
        IPage<SysUser> page =new Page<>(parm.getCurrentPage(), parm.getPageSize());
        //构造查询条件
        QueryWrapper<SysUser> query = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(parm.getNickName())){
            query.lambda().like(SysUser::getNickname, parm.getNickName());
        }
        if (StringUtils.isNotEmpty(parm.getPhone())){
            query.lambda().like(SysUser::getPhone, parm.getPhone());
        }
        query.lambda().orderByDesc(SysUser::getCreateTime);
        IPage<SysUser> list = sysUserService.page(page, query);
        return ResultUtils.success("查询成功",list);
    }

    //根据用户id查询用户角色
    @GetMapping("/getRoleList")
    public ResultVo getRoleListByUserId(Long userId){
        QueryWrapper<SysUserRole> query = new QueryWrapper<>();
        query.lambda().eq(SysUserRole::getUserId, userId);
        List<SysUserRole> list = sysUserRoleService.list(query);
        //角色Id
        List<Long> roleList = new ArrayList<>();
        Optional.ofNullable(list).orElse(new ArrayList<>())
            .forEach(item->{
                roleList.add(item.getRoleId());
            });
        return ResultUtils.success("查询成功",roleList);
    }

    //重置密码
    @PreAuthorize("hasAuthority('sys:user:resetPassword')")
    @PostMapping("/resetPassword")
    public ResultVo resetPassword(@RequestBody SysUser sysUser){
        UpdateWrapper<SysUser> query =new UpdateWrapper<>();
        query.lambda().eq(SysUser::getUserId, sysUser.getUserId())
            .set(SysUser::getPassword, passwordEncoder.encode("123456"));
        if(sysUserService.update(query)){
            return ResultUtils.success("密码重置成功");
        }
        return ResultUtils.error("密码重置失败");
    }

    //图片验证码
    @PostMapping("/getImage")
    public ResultVo imageCode(HttpServletRequest request) {
        // 获取session
        HttpSession session = request.getSession();
        // 生成验证码
        String text = defaultKaptcha.createText();
        // 存入session，并设置有效期
        session.setAttribute("code", text);
        // 生成图片
        BufferedImage bufferedImage = defaultKaptcha.createImage(text);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            // 将图片写入输出流
            ImageIO.write(bufferedImage, "jpg", outputStream);
            // 转换为 base64
            String base64 = Base64.encodeBase64String(outputStream.toByteArray());
            String captchaBase64 = "data:image/jpeg;base64," + base64.replaceAll("\r\n", "").replaceAll("\n", "");
            // 返回结果
            return new ResultVo("生成成功", 200, captchaBase64);
        } catch (IOException e) {
            e.printStackTrace();
            // 返回错误信息
            return new ResultVo("生成验证码失败", 500, null);
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //登录
    @PostMapping("/login")
    public ResultVo login(HttpServletRequest request,@RequestBody LoginParm parm){
        //获取前端传递过来的验证码
        String code = parm.getCode();
        //获取session
        HttpSession session = request.getSession();
        //获取session里的code
        String code1 = (String) session.getAttribute("code");
        if (StringUtils.isEmpty(code1)) { // 判断 session 中的验证码是否为空
            return ResultUtils.error("验证码过期");
        }
        //判断前端传递过来的凑得和session是否相等
        if (!code1.equals(code)){
            return ResultUtils.error("验证码不正确");
        }
        //加密后的密码
        String password = passwordEncoder.encode(parm.getPassword());
        //查询用户信息,交给springsSecurity查询
        UsernamePasswordAuthenticationToken authenticationToken =
            new UsernamePasswordAuthenticationToken(parm.getUsername(),parm.getPassword());
        Authentication authenticate =
            authenticationManager.authenticate(authenticationToken);
        //交给springsSecurity
        SecurityContextHolder.getContext().setAuthentication(authenticate);
        //获取用户信息
        SysUser user =(SysUser) authenticate.getPrincipal();
//        QueryWrapper<SysUser> query = new QueryWrapper<>();
//        query.lambda().eq(SysUser::getUsername, parm.getUsername())
//                .eq(SysUser::getPassword, parm.getPassword());
//        SysUser one = sysUserService.getOne(query);
//        if (one == null){
//            return ResultUtils.error("用户名或密码不正确");
//        }
        //返回用户信息和token
        LoginVo vo = new LoginVo();
        vo.setUserId(user.getUserId());
        vo.setNickName(user.getNickname());
        //生成token
        Map<String,String> map =new HashMap<>();
        map.put("userId",Long.toString(user.getUserId()));
        map.put("username",user.getUsername());
        String token = jwtUtils.generateToken(map);
        vo.setToken(token);
        return ResultUtils.success("登录成功",vo);
    }

    //查询菜单树
    @GetMapping("/getAssignTree")
    public ResultVo getAssignTree(AssignTreeParm parm){
        AssignTreeVo assignTree = sysUserService.getAssignTree(parm);
        return ResultUtils.success("查询成功",assignTree);
    }

    //修改密码
    @PostMapping("/updatePassword")
    public ResultVo updatePassword(@RequestBody UpdatePasswordParm parm){
        SysUser user = sysUserService.getById(parm.getUserId());
//        if(!parm.getOldPassword().equals(user.getPassword())){
//            return ResultUtils.error("原密码不正确");
//        }
        if(!passwordEncoder.matches(parm.getOldPassword(),user.getPassword())){
            return ResultUtils.error("原密码不正确");
        }
        //更新条件
        UpdateWrapper<SysUser> query = new UpdateWrapper<>();
        query.lambda().set(SysUser::getPassword,passwordEncoder.encode(parm.getPassword()))
            .eq(SysUser::getUserId, user.getUserId());
        if(sysUserService.update(query)){
            return ResultUtils.success("修改成功");
        }
        return ResultUtils.error("修改失败");
    }

    //获取用户信息
    @GetMapping("/getInfo")
    public ResultVo getInfo(Long userId){
        //根据id查询用户的信息
        SysUser user = sysUserService.getById(userId);
        List<SysMenu> menuList = null;
        //判断是否为超级管理员
        if(StringUtils.isNotEmpty(user.getIsAdmin()) &&"1".equals(user.getIsAdmin())){
            //是超级管理员
            menuList = sysMenuService.list();
        }else {
            menuList =sysMenuService.selectMenuByUserId(userId);
        }
        List<String> collect = Optional.ofNullable(menuList).orElse(new ArrayList<>())
            .stream()
            .filter(item -> item!=null && StringUtils.isNotEmpty(item.getCode()))
            .map(item -> item.getCode())
            .collect(Collectors.toList());
        //设置返回值
        UserInfo userInfo = new UserInfo();
        userInfo.setName(user.getNickname());
        userInfo.setUserId(user.getUserId());
        userInfo.setPermissions(collect.toArray());
        return ResultUtils.success("查询成功",userInfo);
    }

    //退出登录
    @PostMapping("/loginOut")
    public ResultVo loginOut(HttpServletRequest request, HttpServletResponse response){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication != null){
            new SecurityContextLogoutHandler().logout(request,response,authentication);
        }
        return ResultUtils.success("退出成功");
    }
}
